/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  					        abstract_resource_cache.h

	$Header: /game/abstract_resource_cache.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( ABSTRACT_RESOURCE_CACHE_H_INCLUDED )
#define ABSTRACT_RESOURCE_CACHE_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <string>

#include "abstract_resource_file.h"
#include "cache_base.h"
#include "cached_ptr.h"

// -------------------------------------------------------------------
// t_abstract_resource_cache_base class
// -------------------------------------------------------------------

class t_abstract_resource_cache_base : public t_cache_base
{
public:
	std::string get_name(); // does alter the contents, so cannot be const

protected:
	// Constructors/Destructor
	t_abstract_resource_cache_base( std::string const & name );

	// Member functions
	bool		create( t_progress_handler* handler );
	virtual int	get_size();

	t_abstract_resource_file_ptr m_file;
	int                          m_offset;
private:
	bool                find_resource();
	virtual char const* get_prefix() const = 0;
	virtual bool        read( std::streambuf& buffer, t_progress_handler* handler ) = 0;

	std::string                  m_name;
	int                          m_size;
	bool                         m_valid;
};

// -------------------------------------------------------------------
// t_abstract_resource_cache_data class template
// -------------------------------------------------------------------

template < typename type >
class t_abstract_resource_cache_data : public t_abstract_cache_data< type >, 
                                       public t_abstract_resource_cache_base
{
public:
	// Constructors/Destructor
	t_abstract_resource_cache_data( std::string const & name );
	virtual ~t_abstract_resource_cache_data();

	virtual int get_load_cost();
protected:
	// Member functions
	virtual void	add_reference();
	virtual type *	do_get( t_progress_handler* );
	virtual void	release_memory();
	virtual void	remove_reference();
	virtual bool	read( std::streambuf & stream, t_progress_handler* handler );
	virtual type *	do_read( std::streambuf & stream, t_progress_handler* handler ) = 0;

	// Data members
	type *		m_data_ptr;
};

template < typename type >
inline t_abstract_resource_cache_data< type >::t_abstract_resource_cache_data( std::string const & name )
	:	t_abstract_resource_cache_base( name ),
		m_data_ptr( 0 )
{
}

template < typename type >
inline t_abstract_resource_cache_data< type >::~t_abstract_resource_cache_data()
{
	delete m_data_ptr;
}

template < typename type >
void t_abstract_resource_cache_data< type >::add_reference()
{
	t_abstract_resource_cache_base::add_reference();
}

template < typename type >
type * t_abstract_resource_cache_data< type >::do_get( t_progress_handler* handler )
{
	if ( m_data_ptr == 0 && !create( handler ) )
		return 0;
	return m_data_ptr;
}

template < typename type >
int t_abstract_resource_cache_data< type >::get_load_cost()
{
	if (m_data_ptr != 0)
		return 0;
	return get_size();
}

template < typename type >
void t_abstract_resource_cache_data< type >::remove_reference()
{
	t_abstract_resource_cache_base::remove_reference();
}

template < typename type >
void t_abstract_resource_cache_data< type >::release_memory()
{
	delete m_data_ptr;
	m_data_ptr = 0;
}

template < typename type >
bool t_abstract_resource_cache_data< type >::read( std::streambuf & stream, t_progress_handler* handler )
{
	m_data_ptr = do_read( stream, handler );
	return m_data_ptr != 0;
}

#endif // !defined( ABSTRACT_RESOURCE_CACHE_H_INCLUDED )
